package com.thy.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hospital.common.base.PageResult;
import com.hospital.common.base.ThreadAttributes;
import com.hospital.common.dto.management.module.InitPatientInfoDto;
import com.hospital.common.dto.management.module.PatientInfoDto;
import com.hospital.common.dto.management.module.PatientQueryDto;
import com.hospital.common.enums.RoleType;
import com.hospital.common.enums.auth.module.InitFlag;
import com.thy.pojo.TPatientInfo;
import com.hospital.common.pojo.TUser;
import com.hospital.common.utils.ThreadLocalUtils;
import com.hospital.common.vo.management.module.PatientInfoVo;
import com.thy.exception.PatientInfoServiceException;
import com.thy.exception.enums.PatientInfoServiceExpCode;
import com.thy.mapper.TPatientInfoMapper;
import com.thy.service.TPatientInfoService;
import com.thy.service.TUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;

/**
 * <p>
 * 患者信息 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-09-13
 */
@Service
public class TPatientInfoServiceImpl extends ServiceImpl<TPatientInfoMapper, TPatientInfo> implements TPatientInfoService {
    @Autowired
    private TPatientInfoMapper patientInfoMapper;
    @Autowired
    private TUserService userService;

    @Override
    public PageResult<PatientInfoVo> getAllPatientInfo(Integer pageNum, Integer pageSize) {
        Page<PatientInfoVo> page = new Page<>(pageNum,pageSize);
        IPage<PatientInfoVo> patientInfoVos = patientInfoMapper.getAllPatientInfo(page);
        if (patientInfoVos != null){
            return new PageResult<>(patientInfoVos.getTotal(), patientInfoVos.getRecords());
        }else{
            return new PageResult<>(0L, new ArrayList<>());
        }
    }

    @Override
    public PatientInfoVo getPatientInfo(Long userId) {
        return patientInfoMapper.getPatientInfo(userId);
    }

    @Override
    @Transactional
    public void updatePatientInfo(PatientInfoDto patientInfoDto) {
        LambdaUpdateWrapper<TPatientInfo> wrapper = new LambdaUpdateWrapper<>();
        LambdaUpdateWrapper<TUser> userWrapper = new LambdaUpdateWrapper<>();
        ThreadAttributes threadAttributes = ThreadLocalUtils.get();
        if(ObjectUtils.isEmpty(threadAttributes)){
            throw new PatientInfoServiceException(PatientInfoServiceExpCode.USER_NOT_EXIST);
        }
        userWrapper.eq(TUser::getId, threadAttributes.getUserId())
                .eq(TUser::getRole, threadAttributes.getRoleType())
                .set(TUser::getName, patientInfoDto.getName())
                .set(TUser::getPhone, patientInfoDto.getPhone())
                .set(TUser::getSex, patientInfoDto.getSex());
        wrapper.eq(TPatientInfo::getId,patientInfoDto.getId())
                .set(TPatientInfo::getAddress, patientInfoDto.getAddress());
        if(!userService.update(userWrapper)){
            throw new PatientInfoServiceException(PatientInfoServiceExpCode.UPDATE_USER_FAILED);
        }
        if(patientInfoMapper.update(wrapper)==0){
            throw new PatientInfoServiceException(PatientInfoServiceExpCode.UPDATE_PATIENT_INFO_FAILED);
        }
    }

    @Override
    @Transactional
    public void initPatientInfo(InitPatientInfoDto initPatientInfoDto) {
        ThreadAttributes threadAttributes = ThreadLocalUtils.get();
        if(ObjectUtils.isEmpty(threadAttributes)){
            throw new PatientInfoServiceException(PatientInfoServiceExpCode.USER_NOT_EXIST);
        }
        TUser user = userService.getById(threadAttributes.getUserId());
        if(ObjectUtils.isEmpty(user)){
            throw new PatientInfoServiceException(PatientInfoServiceExpCode.USER_NOT_EXIST);
        }
        if(!user.getInit().equals(InitFlag.NONE.value)){
            throw new PatientInfoServiceException(PatientInfoServiceExpCode.USER_HAS_INITIALIZED);
        }
        TPatientInfo patientInfo = TPatientInfo.builder().address(initPatientInfoDto.getAddress())
                .identityCard(initPatientInfoDto.getIdentityCard())
                .medicalCard(initPatientInfoDto.getMedicalCard()).build();
        if(patientInfoMapper.insert(patientInfo)==0){
            throw new PatientInfoServiceException(PatientInfoServiceExpCode.INSERT_PATIENT_INFO_FAILED);
        }
        user.setInfoId(patientInfo.getId());
        user.setInit(InitFlag.INITIALIZED.value);
        if(!userService.updateById(user)){
            throw new PatientInfoServiceException(PatientInfoServiceExpCode.UPDATE_USER_FAILED);
        }
    }

    @Override
    public PageResult<PatientInfoVo> query(PatientQueryDto patientQueryDto) {
        LambdaQueryWrapper<TUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TUser::getRole, RoleType.PATIENT.value);
        if(!ObjectUtils.isEmpty(patientQueryDto.getAccount())){
            queryWrapper.eq(TUser::getAccount, patientQueryDto.getAccount());
        }
        if(!ObjectUtils.isEmpty(patientQueryDto.getSex())){
            queryWrapper.eq(TUser::getSex, patientQueryDto.getSex());
        }
        if(!ObjectUtils.isEmpty(patientQueryDto.getName())){
            queryWrapper.like(TUser::getName, patientQueryDto.getName());
        }
        Page<TUser> page = userService.page(new Page<>(patientQueryDto.getPageNum(),patientQueryDto.getPageSize()),queryWrapper);
        return new PageResult<>(page.getTotal(),page.getRecords().stream().map(this::convert).toList());
    }
    private PatientInfoVo convert(TUser user){
        PatientInfoVo patientInfoVo = new PatientInfoVo();
        patientInfoVo.setId(String.valueOf(user.getInfoId()));
        patientInfoVo.setName(user.getName());
        patientInfoVo.setSex(String.valueOf(user.getSex()));
        patientInfoVo.setPhone(user.getPhone());
        patientInfoVo.setAccount(user.getAccount());
        patientInfoVo.setCreateTime(user.getCreateTime());
        LambdaQueryWrapper<TPatientInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TPatientInfo::getId, user.getInfoId());
        TPatientInfo patientInfo = patientInfoMapper.selectOne(queryWrapper);
        if(!ObjectUtils.isEmpty(patientInfo)){
            patientInfoVo.setAddress(patientInfo.getAddress());
            patientInfoVo.setIdentityCard(patientInfo.getIdentityCard());
            patientInfoVo.setMedicalCard(patientInfo.getMedicalCard());
        }
        return patientInfoVo;
    }
}
